//! 生成用于智能配网的组播包和解码校验
//!
//!
//!
//! - 组播包生成
//! ```
//! fn main() {
//!     let ds = smartconfig::make_multicast_addr("wifi_name", "wifi_pwd");
//!     let udp = std::net::UdpSocket::bind("0.0.0.0:0").unwrap();
//!     
//!     loop {
//!         for ip in &ds {
//!             udp.send_to(&[0][..], (ip.clone(), 14501)).ok();
//!             println!("{}", ip.to_string());
//!             std::thread::sleep(Duration::from_millis(50));
//!             udp.send_to(&[0][..], (ip.clone(), 14501)).ok();
//!             std::thread::sleep(Duration::from_millis(50));
//!         }
//!         std::thread::sleep(Duration::from_millis(100));
//!     }
//! }
//! ```

use std::net::{IpAddr, Ipv4Addr};

/// 输入SSID和密码
fn generate_multicast_packets(ssid: &str, password: &str) -> Vec<[u8; 3]> {
    let ssid_len = ssid.as_bytes().len();
    let pwd_len = password.as_bytes().len();
    // 新的编码方法
    let mut vec = vec![[0x6c, 0x79, 0x92]];
    let total = (ssid_len + pwd_len + 1) as u8;
    vec.push([0 + 0x0a, total, 0x0au8.wrapping_add(total / 2)]);
    let mut i = 0;
    for d in ssid.as_bytes() {
        i += 1;
        vec.push([i + 0x0a, *d, 0x0au8.wrapping_add(i + *d / 2)]);
    }
    i += 1;
    vec.push([i + 0x0a, 0, i + 0x0a]);
    for d in password.as_bytes() {
        i += 1;
        vec.push([i + 0x0a, *d, 0x0au8.wrapping_add(i + *d / 2)]);
    }
    vec
}

/// 把ssid和pwd编码到组播地址
///
/// 逐个给各个组播地址发任意数据即可
pub fn make_multicast_addr(ssid: &str, password: &str) -> Vec<IpAddr> {
    let dd = generate_multicast_packets(ssid, password);
    dd.iter()
        .map(|m| IpAddr::V4(Ipv4Addr::new(224, m[0], m[1], m[2])))
        .collect()
}

pub struct SmartConfigInfo {
    pub ssid: String,
    pub pwd: String,
}

/// 提取编码在组播地址末尾的数据
///
///  合并成u8数组，长度一定是偶数
pub fn parse(data: &[u8]) -> Option<SmartConfigInfo> {
    let zero = data.iter().position(|&x| x == 0);
    zero.map(|z| {
        let ssid = String::from_utf8_lossy(&data[..z]).into();
        let pwd = String::from_utf8_lossy(&data[z + 1..]).into();
        SmartConfigInfo { ssid, pwd }
    })
}
